#include "NZ/NZparser.h"
#include <QDebug>
#include "utils.h"
#include <QMapIterator>
#include <QMap>

NZParser::NZParser()
{
    // 确认定值组组号 03

    // 初始化成员变量 m_billValueGroup
}

NZParser::~NZParser()
{
}

bool NZParser::parseRecvPacket(const QByteArray &pData, int packetLength)
{
    QString packet = pData;
    Utils::washPacket(packet);
    if (packetLength > 14)  // 最小长度14，无数据的情况下可变帧长数据
    {
        parseVariableData(packet, packetLength);
    }
    else    // 固定帧长报文
    {
        qDebug() << "not ASDU10 ";
    }

    return true;
}

void NZParser::parseASDU10(const QString &packet, int length)
{
    int fun = packet.mid(FUN_POSI_NZ, 2).toUInt(nullptr,16);
    int inf = packet.mid(INF_POSI_NZ, 2).toUInt(nullptr,16);

    length = packet.size()/2;

    // 1. 通用分类数据响应命令
    if (FUN_GEN == fun && 0xF0 == inf) //通用分类数据响应命令（装置响应的读目录）
    {

    }

    // 2. 读指定定值组的所有条目的响应，中文名称，值，缺省值，最大最小值，步长，单位
    if ( FUN_GEN == fun && 0xF0 == inf )
    {
        parseASDU10AllValue_GDNZ(packet);
    }
    // 3. 读指定一个条目的描述或者值
    else if ( FUN_GEN == fun && INF_READ_GROUP == inf )
    {
        parseASDU10AllValue_GDNZ(packet);
    }
    else if ( FUN_GEN == fun && INF_READ_EBTRY == inf )   // 带确认的写条目响应
    {
        parseASDU10AllValue_GDNZ(packet);
    }
    else if ( FUN_GEN == fun && INF_EXEC_WRITE == inf ) // 带执行的写条目响应
    {
        QString rii = packet.mid(RII_POSI_NZ,2);
    }
    else
    {
        qDebug() << "unknow asdu10: "<<packet;

    }

    return ;
}

//bool NZParser::parseFixedData(const QString &pData, int dataLen)
//{



//    return true;
//}

bool NZParser::parseVariableData(const QString &pData, int dataLen)
{
    QString asduType = pData.mid(0,2); // asdu类型

    switch(asduType.toUInt(nullptr,16))        // 设备回主站都是 OA 开头的回答服务
    {
        case ASDU_10:
            parseASDU10(pData, dataLen);
            break;
        default:
            break;
    }

    return true;
}

vector<OneDataSetStruct> NZParser::parseASDU10AllValue_GDNZ(const QString &packet)
{
    // 返回的数据个数
    // 类型标识
    QString typeID = packet.mid(0,2);

    // 解析报文头，前7个字节
    QString ngd=packet.mid(14,2);  // 通用分类数据集数目，表示后面有多少个数据
    uint8_t ngd_int =  Utils::calNgdNo(ngd);
    QString dataArea = packet.mid(16,-1);   //从第8个开始截取报文的全部数据集元素

    qDebug() << "全部的报文数据为: " << packet;
    qDebug() << "全部的数据集为：  " <<dataArea;

    // 解析用户数据段
    // 1.组号，2.条目号，3.描述类别，4.数据类型，5.数据宽度，6.数目，7.数据
    // 整个数据的长度 = 6*2 + 【数值长度】，数据宽度值等于数据长度 ， 数据宽度 * 数目

    int dataOffset = 0;     // 每一个数据的宽度都可能不一样
    vector<OneDataSetStruct> allData;        // 需要返回的数据
    OneDataSetStruct tmpDataSet;
    qDebug() << " ngd 16进制 = " << ngd_int;        // 数据集元素个数
    for (int i=0; i<ngd_int; i++)
    {
        tmpDataSet.m_ginGroup = dataArea.mid(dataOffset, 2);
        tmpDataSet.m_ginNo = dataArea.mid(dataOffset + 2, 2);
        tmpDataSet.m_kod = dataArea.mid(dataOffset + 4, 2);   //每一个数据占的字节数据
        //qDebug() << "the kod =  " << dataArea.mid(dataOffset + 4, 2);
        tmpDataSet.m_dataType = dataArea.mid(dataOffset + 6, 2);
        tmpDataSet.m_dataWidth = dataArea.mid(dataOffset + 8, 2);
        tmpDataSet.m_dataNum = dataArea.mid(dataOffset + 10, 2);

        //分析数据类型
        tmpDataSet.m_dataValue = dataArea.mid(dataOffset + 12, 2* tmpDataSet.m_dataNum.toInt(nullptr,16) * tmpDataSet.m_dataWidth.toInt(nullptr,16));
        allData.push_back(tmpDataSet);

        dataOffset = dataOffset + ( 12 + 2 * tmpDataSet.m_dataNum.toInt(nullptr,16) * tmpDataSet.m_dataWidth.toInt(nullptr,16) );
    }

    //showDataSets(allData);

    return allData;
}

 // 解析接收的报文
int NZParser::recvPacketTypeFilter(const QByteArray &packet)
{
    qDebug() << "recvPacketTypeFilter线程 ID = " << QThread::currentThreadId();

    // 对报文返回进行判断 , 1.返回信息标识符号相同 2.有效数据恢复cot=2A 3.是通用服务 4.信息序号是一个组的”F1“值或属性描述
    int type = -3;
    QByteArray asduType = packet.mid(POS_TYPE, 2);
    QByteArray cot = packet.mid(POS_COT, 2);
    QByteArray fun = packet.mid(POS_FUN, 2);
    QByteArray inf = packet.mid(POS_INF, 2);
    QByteArray rii = packet.mid(POS_RII, 2);
    QByteArray ngd = packet.mid(POS_NGD, 2);     // 数据集元素的个数，读定值区时只有一个值， 定值组布置一个定值
    QByteArray groupNo = packet.mid(POS_GROUP_NO, 2);
    QByteArray ginNo = packet.mid(POS_GINNO, 2);
    QByteArray kod = packet.mid(POS_KOD, 2);

    qDebug() << "********* 组 =  " << groupNo << "ngd = " << ngd << "ginNo = " <<ginNo << "kod = " << kod ;
    qDebug() << "全部有关组 = "<<m_billValueGroups;
//    m_billValueGroups.append("03");     // 测试 ，，强制给值
    // 确认是否是通用分类读的有效响应
    {
        qDebug() << "待解析的asdu基本信息 "<< asduType << cot << fun << inf;
    }

    if ( asduType == "0A" /*&& rii == ASDU_RII*/ && (cot.toLower() == COT_S2C_GENERAL_READ_STR || cot == COT_S2C_CIRCLE_SEND_STR) && fun =="FE")
    {
        qDebug() << "有效数据响应。。。。";
        if ( inf == "F1" )   // 是对一个组的读取操作
        {
            qDebug() << "对读指定组的有效数据响应。。。。";
            qDebug() << "读取实际定值的值" << Utils::uintStrToHexStr(groupNo,2);
            if ( kod == KOD_DESCRIPTER )
            {
                type = REPLY_READ_SETTINGS_NAME;
            }
            else if ( kod == KOD_REAL_VALUE )
            {
                if ( groupNo == Utils::uintStrToHexStr(m_deviceSysGroup,2)  && ginNo == SETTING_AREA_GINNO )    // 是系统参数组中定值区的实际值,这个 “00" 应该是在读取标题时候确认的
                {
                    type = REPLY_READ_SETTINGS_AREA;
                    qDebug () << "读取定值区号的实际值， 组号 = " << m_deviceSysGroup << ", 条目 = " << ginNo;
                }
                //读压板组的实际值
                else if ( groupNo == m_ybGroup )           // 实际"OE", 由读全部组的标题来确认组号哪个是压板组，哪个是定值组
                {
                    type = REPLY_READ_YB;
                }
               /* else if (groupNo == m_billValueGroup) */          // 判断是读定值组的实际值
                else if (m_billValueGroups.contains(Utils::removeZero(groupNo)))
                {
                      // 是读的定值组s的全部的值
                    qDebug() << "是读的定值组的全部的值";
                    type = REPLY_READ_SETTINGS_CURRVALUE;
                }
            }
            else if ( kod == KOD_DEFAULT_VALU )
            {
                type = REPLY_READ_DEFAULTVALUE;
            }
            else if ( kod == KOD_DIMENSION )
            {
                type = REPLY_READ_SETTINGS_MIN;
            }
            else if ( kod == KOD_UNIT )
            {
                type = REPLY_READ_SETTINGS_UNIT;
            }
            else {
                type = -1;
            }
        }
        else if ( inf == "F0" )    // 只读全部组的标题
        {
            type = REPLY_TYPE_ALL_GROUP_TITLE;
        }

    }
    //待解析的asdu基本信息  "0A" "2A" "FE" "F1"
    if ( inf == "FA" && cot == COT_S2C_GENERAL_WRITE_STR  && groupNo == "00")  //0A 81 28 01 FE FA 77 0100020103010100
    {
        type = REPLY_READ_SURE_AREA;
    }

    qDebug() << "recv filter 类型" << type;

    return  type;
}

QStringList NZParser::parseBillValueNames(const QByteArray &packet)
{
    QStringList names;

    // 解析接收的报文
    NZParser parser;
    vector<OneDataSetStruct> dataSets = parser.parseASDU10AllValue_GDNZ(packet);
    //QString billValueGroup = "03";
    foreach (OneDataSetStruct it, dataSets)
    {
        // 定值的名称描述,确认读的组号
        // qDebug() << "组号 " << it.m_ginGroup.toInt(nullptr,16) << ", 汉字表示： "  << Utils::GBKToUTF8(it.m_dataValue);
        //if(it.m_ginGroup == m_billValueGroup)
        names.append(Utils::GBKToUTF8(it.m_dataValue));
        qDebug() << "获取到更新的名字"  << Utils::GBKToUTF8(it.m_dataValue);
    }

    return names;
}

QStringList NZParser::parseBillValueUnits(const QByteArray &packet)
{
    QStringList  units;
    NZParser parser;
    vector<OneDataSetStruct> dataSets =  parser.parseASDU10AllValue_GDNZ(packet);
    QString billValueGroup = "03";
    foreach (OneDataSetStruct it, dataSets)
    {
//        if (it.m_ginGroup == billValueGroup )
        {
            // qDebug() << "组号 " << it.m_ginGroup.toInt(nullptr,16) << ", 汉字表示： "  << Utils::GBKToUTF8(it.m_dataValue);
            //if(it.m_ginGroup == m_billValueGroup)

            if ( Utils::GBKToUTF8(it.m_dataValue) == " " || Utils::GBKToUTF8(it.m_dataValue) == "" )
            {
                units.append("无");
            }
            else
            {
                units.append(Utils::GBKToUTF8(it.m_dataValue));
            }

            qDebug() << "获取到单位："  << Utils::GBKToUTF8(it.m_dataValue);
        }
    }

    QString groupNo =  dataSets.at(0).m_ginNo;
    //m_billTablesMap[groupNo].billRealValueList.append(units);      // 将结果存到缓存

    return units;
}

QStringList NZParser::parseBillDimension(const QByteArray &packet)
{
    QStringList m_billValueMinList,m_billValueMaxList,m_billValueStepList;
    // 解析接收的报文
    NZParser parser;
    vector<OneDataSetStruct> dataSets =  parser.parseASDU10AllValue_GDNZ(packet);
    QString billValueGroup = "03";
    foreach (OneDataSetStruct it, dataSets)
    {
        qDebug() << "读取定值的最大最小值和步长"<< it.m_dataValue;
        if (it.m_dataNum =="03" || it.m_dataNum == "02")
        {
            if( it.m_dataType == "06" || it.m_dataType == "07") // 浮点数或者短实数
            {
                qDebug() << "浮点数量程： "<<Utils::parseFloatTypeMinMaxStep(it.m_dataValue);
                m_billValueMinList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[0]);
                m_billValueMaxList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[1]);
                m_billValueStepList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[2]);
            }
            else if ( it.m_dataType == "03" )   // 整数量程
            {
                qDebug() << "整数量程：" << it.m_dataValue << it.m_dataWidth << Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16));
                switch ( Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16)).count())
                {
                case 0 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append("no");
                    break;
                case 1 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[0]);
                    break;
                case 2 :
                    m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[0]);
                    m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[1]);
                    m_billValueStepList.append("no");
                    break;
                case 3:
                    m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[0]);
                    m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[1]);
                    m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[2]);
                    break;
                }
            }
            else if( it.m_dataType == "04")
            {
                qDebug() << "整数量程：" << it.m_dataValue << it.m_dataWidth << Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16));

                QStringList dataValueList = Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16));
                switch ( dataValueList.count())
                {
                case 0 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append("no");
                    break;
                case 1 :
                    m_billValueMinList.append("no");
                    m_billValueMaxList.append("no");
                    m_billValueStepList.append(Utils::hexStrToIntStr(dataValueList[0]));
                    break;
                case 2 :
                    m_billValueMinList.append(Utils::hexStrToIntStr(dataValueList[0]));;
                    m_billValueMaxList.append(Utils::hexStrToIntStr(dataValueList[1]));
                    m_billValueStepList.append("no");
                    break;
                case 3 :
                    m_billValueMinList.append(Utils::hexStrToIntStr(dataValueList[0]));
                    m_billValueMaxList.append(Utils::hexStrToIntStr(dataValueList[1]));
                    m_billValueStepList.append(Utils::hexStrToIntStr(dataValueList[2]));
                    break;
                }
            }
            else if (it.m_dataType == "01")  // ASCII8位码量程,都是不存在最大最小步长值的
            {
                if(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue).count() !=3)
                {
                    m_billValueMinList.append("无");
                    m_billValueMaxList.append("无");
                    m_billValueStepList.append("无");
                }
                else
                {
                    int width = it.m_dataWidth.toInt(nullptr,16);
                    QString  strList = Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                    // 将strList按照 单个宽度进行分割
                    qDebug() << "ASCII8位码量程：" <<Utils::mixCharToWord(strList,width);
                    m_billValueMinList.append(Utils::mixCharToWord(strList,width)[0]);
                    m_billValueMaxList.append(Utils::mixCharToWord(strList,width)[1]);
                    m_billValueStepList.append(Utils::mixCharToWord(strList,width)[2]);
                }
            }
        }
    }

    QStringList ret =  (m_billValueMinList + m_billValueMaxList + m_billValueStepList);

    QString groupNo = dataSets.at(0).m_ginGroup;

    return ret;
}

QStringList NZParser::parseBillInfo(const int replyType, const QByteArray &packet)
{
    QStringList result;

    // 获取当前响应的组号
    QString groupNo = Utils::hexNumToDecNum(packet.mid(POS_ASDU_GROUPNO, 2));
    qDebug() << "*******解析 table info ********* 组号 = " << groupNo;

    switch (replyType)
    {
    case REPLY_TYPE_ALL_GROUP_TITLE:
        result = parseBillTitles(packet);
        break;
    case REPLY_READ_SETTINGS_NAME:
        result = parseBillValueNames(packet);
        m_billTablesMap[groupNo].billNameList = result;
        break;
    case REPLY_READ_SETTINGS_CURRVALUE:
        m_billTablesMap[groupNo].billRealValueList = parseBillRealValue(packet);
        result = parseBillRealValue(packet);
        break;
    case REPLY_READ_DEFAULTVALUE:       // 缺省值读取时候获取数据类型
        result = parseBillDefaultValue(packet) +  parseBillValueDataTypes(packet) ;
        m_billTablesMap[groupNo].billDefaultValueList = parseBillDefaultValue(packet);
        m_billTablesMap[groupNo].billTypeList = parseBillValueDataTypes(packet);
        break;
    case REPLY_READ_SETTINGS_MIN:
        result = parseBillDimension(packet);
        qDebug() << " 解析定值量程 -- " << result;
        m_billTablesMap[groupNo].billMinList = (result.mid(0, result.count()/3));
        m_billTablesMap[groupNo].billMaxList = (result.mid((result.count()/3), result.count()/3));
        m_billTablesMap[groupNo].billStepsList = (result.mid(( 2 * result.count()/3), result.count()/3 ));
        break;
    case REPLY_READ_SETTINGS_UNIT:
        result = parseBillValueUnits(packet);
        m_billTablesMap[groupNo].billUnitList = (result);
        break;
    case REPLY_READ_SETTINGS_AREA:
        result = parseBillArea(packet);
        m_billTablesMap["DZQH"].billRealValueList = result;
        m_billTablesMap["DZQH"].billNameList.append("定值区号");
        break;
    default:
        result = parseBillUnkown();   // 未知类型
        break;
    }

    return result;
}

QMap<QString, QString> NZParser::getAboutBillGroupInfo(QString &key)
{
    QMap<QString, QString> ret;

    foreach (QString it, m_groupNoNameMap.keys())
    {
        if ( m_groupNoNameMap[it].contains(key) )
        {
            ret[it] = m_groupNoNameMap[it];

            m_billTablesMap[it].groupName =  m_groupNoNameMap[it];     // 开启数据缓存空间
            m_billTablesMap[it].groupNo =  it;     // 开启数据缓存容量
        }
    }

    return ret;
}

void NZParser::clearBillTableBuffer()
{
    m_billTablesMap.clear();
}

QMap<QString, BillTableStruct> NZParser::getBillTableInfo()
{
//    qDebug() <<"NZParser 结果个数" << m_billTablesMap.count();
    return m_billTablesMap;
}

void NZParser::slot_parseBillInfo(const QByteArray &packet)
{
    qDebug() << "开始进入接收报文的处理, 当前线程 id = " << QThread::currentThreadId();
    // 判断是不是读所有定值名字

    // 1.判断返回报文的服务类型
    int type = recvPacketTypeFilter(packet);

    if (type == REPLY_READ_SETTINGS_AREA)    //读取定值区类型回复
    {
        QStringList result = parseBillInfo(type, packet);
        // m_currentBillArea = result.first();
        if ( false == result.isEmpty() ) {
            emit sig_getBillAreaFinished(result.first());         // 通知已经收到读定值区号的响应，可以读该定值区的信息了
            emit signal_parseFinished(result, type);
        }
    }

    if (type == REPLY_TYPE_ALL_GROUP_TITLE)                  // 确认是读标题的回应
    {
        if (getGroupNoWithName().count() != 0)
        {
            //可以读取定制信息了, 通知启动读取定值有关信息的定时器
            emit sig_getTitleInfoFinished();
        }
    }

    if ( type == REPLY_READ_SURE_AREA ) {           // 完成定值区的选择确认，下一步进行读取定值组具体信息
        emit sig_sureBillAreaFinished();
    }

    qDebug() << "结束接收报文的分类处理 type = " <<type;

    // 2. 确认是否收到有用的消息回复
    if( type > -1 )
    {
        // 进行解析
        qDebug() << "对接收到的消息进行解析处理结果： " ;
        QStringList result = parseBillInfo(type, packet);
        qDebug() << "parse 结果类型 :  " << type << result;
        // 3. 通知 table，是有用消息更新到table中
        emit signal_parseFinished(result, type);
        qDebug() << "结束接收报文的处理";
    }
}

void NZParser::initialBillValueGroupNo(QMap<QString, QString> &groupNoAndName)
{
    QMap<QString,QString>::iterator it;
    for (it = groupNoAndName.begin(); it!=groupNoAndName.end(); ++it)
    {
        qDebug() << " 根据组名关键字对组号分组 = " <<it.key();
        if ( it.value().contains(SETTING_GROUP_NAME) )
        {
             m_billValueGroups.push_back(it.key());
             qDebug() << "找到一个定值组， 组号 = " << it.key() << "组名 = " << it.value();
             m_billTablesMap[it.key()].groupName = it.value();
             m_billTablesMap[it.key()].groupNo = it.key();
        }
        else if (it.value().contains("系统"))
        {
            m_deviceSysGroup = it.key();
            m_billValueGroups.push_back(it.key());
            qDebug() << "找到一个系统组， 组号 = " << it.key() << "组名 = " << it.value();
            m_billTablesMap[it.key()].groupName = it.value();
            m_billTablesMap[it.key()].groupNo = it.key();
        }
        else if (it.value().contains("压板"))
        {
            m_ybGroup = it.key();
        }
    }
}

QStringList NZParser::parseBillTitles(const QByteArray &packet)
{
    vector<OneDataSetStruct> dataSets = parseASDU10AllValue_GDNZ(packet);
    QStringList titiles;
    QStringList groupNoes;
    foreach (OneDataSetStruct it, dataSets)
    {
        titiles.push_back(Utils::hexNumToDecNum(it.m_ginGroup));      // 同时添加到组号
        // 进行简单的判断确认数据正确
        groupNoes.push_back(Utils::GBKToUTF8(it.m_dataValue));
        qDebug() << "添加一个组号和一个" << Utils::hexNumToDecNum(it.m_ginGroup) << Utils::GBKToUTF8(it.m_dataValue);
    }

    getBillTitleGroupNo(packet);

    return titiles+groupNoes;
}

QStringList NZParser::parseBillArea(const QByteArray &packet)
{
    vector<OneDataSetStruct> dataSets  = parseASDU10AllValue_GDNZ(packet);
    QStringList areaValue;
    foreach (OneDataSetStruct it, dataSets)
    {
        // qDebug() << "定值区号： " << Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16));
        areaValue.append(Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16)));
    }

    return areaValue;
}

QStringList NZParser::parseBillDefaultValue(const QByteArray &packet)
{
    // 实际数据,缺省值，准确度
    // 解析接收的报文
    vector<OneDataSetStruct> dataSets =  parseASDU10AllValue_GDNZ(packet);
    QString billValueGroup = "03";
    QStringList billValueDefaultList;         // 存放默认值
    foreach (OneDataSetStruct it, dataSets)
    {
        ///qDebug() << "数据" << ++i << it.m_dataValue;
        if (it.m_dataType == "00")
        {
            qDebug() << "数据无所对应的类型";
            billValueDefaultList.append(" ");
        }
        else if (it.m_dataType == "01")
        {
            qDebug() << "数据类型为 OS8ASCII" << Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
            billValueDefaultList.append(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue));
        }
        else if (it.m_dataType == "03")
        {
            qDebug() << "数据类型为无符号整数" << (Utils::reverseStr(it.m_dataValue).toUInt(nullptr,16));
            billValueDefaultList.append(QString::number((Utils::reverseStr(it.m_dataValue).toUInt(nullptr,16))));
        }
        else if (it.m_dataType == "04")
        {
            billValueDefaultList.append(Utils::hexStrToIntStr(it.m_dataValue));
        }
        else if ( it.m_dataType == "06")
        {
            qDebug() << "数据类型为浮点数" << Utils::hexStrToFloat(it.m_dataValue);     // IEEE 754 短实数
            billValueDefaultList.append(QString::number(Utils::hexStrToFloat(it.m_dataValue)));
        }
        else if (it.m_dataType == "07")      // 数据类型为短实数
        {
            qDebug() <<"数据类型为短实数: " << Utils::hexStrToFloat(it.m_dataValue);
            billValueDefaultList.append(QString::number(Utils::hexStrToFloat(it.m_dataValue)));
        }
        else if (it.m_dataType == "09")
        {
            qDebug() << "数据类型为双点信息" << (Utils::reverseStr(it.m_dataValue)).toInt();        // bool 类型值
            billValueDefaultList.append(Utils::reverseStr(it.m_dataValue));
        }
        else
        {
            if (it.m_dataType == "10")
            {
                qDebug() << "数据类型为单点信息";
            }
            else if (it.m_dataType == "0C")
            {
                qDebug() << "数据类型为带品质描述的被测值";
            }
            else if (it.m_dataType == "13")
            {
                qDebug() << "数据类型为带时标的报文";
            }
            else if (it.m_dataType == "18")
            {
                qDebug() << "数据类型为数据结构";
            }
            else if (it.m_dataType == "CB")
            {
                qDebug() << "数据类型为带7字节的时标报文";
            }
            else if (it.m_dataType == "CC")
            {
                qDebug() << "数据类型为带相对时间的7字节时标报文";
            }
            else if(it.m_dataType == "00")
            {
                qDebug() << "数据类型为无所确定的类型";
            }
        }
    }

    return billValueDefaultList;
}

QStringList NZParser::parseBillRealValue(const QByteArray &packet)
{
    // 实际数据,缺省值，准确度
    // 解析接收的报文
    vector<OneDataSetStruct> dataSets = parseASDU10AllValue_GDNZ(packet);
    QStringList billValueList;         // 存放值
    QStringList billGinNoList;  //条目号信息
    foreach (OneDataSetStruct it, dataSets)
    {
        billGinNoList.append(it.m_ginNo);

        ///qDebug() << "数据" << ++i << it.m_dataValue;
        if (it.m_dataType == "00")
        {
            qDebug() << "数据无所对应的类型";
            billValueList.append(" ");
        }
        else if (it.m_dataType == "01")
        {
            qDebug() << "数据类型为 OS8ASCII" << Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
            billValueList.append(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue));
        }
        else if (it.m_dataType == "03")
        {
            qDebug() << "数据类型为无符号整数" << (Utils::reverseStr(it.m_dataValue).toUInt(nullptr,16));
            billValueList.append(QString::number((Utils::reverseStr(it.m_dataValue).toUInt(nullptr,16))));
        }
        else if(it.m_dataType == "04")
        {
            //qDebug() << "数据类型为整数" << Utils::hexStrToIntStr(it.m_dataValue);
            billValueList.append( Utils::hexStrToIntStr(it.m_dataValue));
        }
        else if( it.m_dataType == "06")
        {
            qDebug() << "数据类型为浮点数" << Utils::hexStrToFloat(it.m_dataValue);     // IEEE 754 短实数
            billValueList.append(QString::number(Utils::hexStrToFloat(it.m_dataValue)));
        }
        else if (it.m_dataType == "07")      // 数据类型为短实数
        {
            qDebug() <<"数据类型为短实数: " << Utils::hexStrToFloat(it.m_dataValue);
            billValueList.append(QString::number(Utils::hexStrToFloat(it.m_dataValue)));
        }
        else if (it.m_dataType == "09")
        {
            qDebug() << "数据类型为双点信息" << (Utils::reverseStr(it.m_dataValue)).toInt();        // bool 类型值
            billValueList.append(Utils::reverseStr(it.m_dataValue));
        }
        else
        {
            if (it.m_dataType == "10")
            {
                qDebug() << "数据类型为单点信息";
            }
            else if (it.m_dataType == "0C")
            {
                qDebug() << "数据类型为带品质描述的被测值";
            }
            else if (it.m_dataType == "13")
            {
                qDebug() << "数据类型为带时标的报文";
            }
            else if (it.m_dataType == "18")
            {
                qDebug() << "数据类型为数据结构";
            }
            else if (it.m_dataType == "CB")
            {
                qDebug() << "数据类型为带7字节的时标报文";
            }
            else if (it.m_dataType == "CC")
            {
                qDebug() << "数据类型为带相对时间的7字节时标报文";
            }
            else if(it.m_dataType == "00")
            {
                qDebug() << "数据类型为无所确定的类型";
            }
        }
    }
    // 取到组号
    QString ginGroup = Utils::hexNumToDecNum(dataSets.at(0).m_ginGroup);
    m_billTablesMap[ginGroup].billGinNoList = billGinNoList;      // 将结果存到缓存
    return billValueList;
}

QStringList NZParser::parseBillUnkown()
{
    QStringList unknow = {"0"};
    return unknow;
}

// 解析定值数据类型，在解析默认值的时候就可以确认
QStringList NZParser::parseBillValueDataTypes(const QByteArray &packet)
{
    // 实际数据,缺省值，准确度
    // 解析接收的报文
    vector<OneDataSetStruct> dataSets =  parseASDU10AllValue_GDNZ(packet);
    QString billValueGroup = "03";
    QStringList dataTypes;         // 存放默认值
    foreach (OneDataSetStruct it, dataSets)
    {
        qDebug() << "数据无所对应的类型";
        dataTypes.append(it.m_dataType);
    }

    QString groupNo = Utils::hexNumToDecNum(dataSets.at(0).m_ginGroup);
    qDebug() << groupNo << "组，数据类型结果:" << dataTypes;
//    m_billTablesMap[groupNo].billRealValueList.append(dataTypes);      // 将结果存到缓存

    return dataTypes;
}

void  NZParser::getBillTitleGroupNo(const QByteArray &packet)
{
    m_groupNoNameMap.clear();
    vector<OneDataSetStruct> dataSets  = parseASDU10AllValue_GDNZ(packet);
    foreach (OneDataSetStruct it, dataSets)
    {
        m_groupNoNameMap[Utils::hexNumToDecNum(it.m_ginGroup)] = Utils::GBKToUTF8(it.m_dataValue);

        qDebug() << "添加一个组号和一个" << Utils::hexNumToDecNum(it.m_ginGroup) << Utils::GBKToUTF8(it.m_dataValue) ;
    }

    // 获取定值组组号信息
    initialBillValueGroupNo(m_groupNoNameMap);
}


void NZParser::showDataSets(vector<OneDataSetStruct> &dataSets)
{
    //根据数据类型来分
    int i=0;
    foreach (OneDataSetStruct it, dataSets)
    {
        // 定值的名称描述
        if (it.m_kod == "0A")
        {
            qDebug() << "数据 " << ++i << it.m_dataValue;
            qDebug() << "组号 " << it.m_ginGroup.toInt(nullptr,16) << ", 汉字表示： "  << Utils::GBKToUTF8(it.m_dataValue);
            //if(it.m_ginGroup == m_billValueGroup)
            m_billValueName.append(Utils::GBKToUTF8(it.m_dataValue));
        }
         // 实际数据,缺省值，准确度
        else if (it.m_kod == "01" || it.m_kod == "02" || it.m_kod == "05")
        {
            ///qDebug() << "数据" << ++i << it.m_dataValue;
            if (it.m_dataType == "00")
            {
                qDebug() << "数据无所对应的类型";
                m_billValueDefaultList.append(" ");
            }
            else if (it.m_dataType == "01")
            {
                qDebug() << "数据类型为 OS8ASCII" << Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                m_billValueDefaultList.append(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue));
            }
            else if (it.m_dataType == "03")
            {
                qDebug() << "数据类型为无符号整数" << (Utils::reverseStr(it.m_dataValue).toUInt(nullptr,16));
                m_billValueDefaultList.append(QString::number((Utils::reverseStr(it.m_dataValue).toUInt(nullptr,16))));
            }
            else if( it.m_dataType == "06")
            {
                qDebug() << "数据类型为浮点数" << Utils::hexStrToFloat(it.m_dataValue);     // IEEE 754 短实数
                m_billValueDefaultList.append(QString::number(Utils::hexStrToFloat(it.m_dataValue)));
            }
            else if (it.m_dataType == "07")      // 数据类型为短实数
            {
                qDebug() <<"数据类型为短实数: " << Utils::hexStrToFloat(it.m_dataValue);
                m_billValueDefaultList.append(QString::number(Utils::hexStrToFloat(it.m_dataValue)));
            }
            else if (it.m_dataType == "09")
            {
                qDebug() << "数据类型为双点信息" << (Utils::reverseStr(it.m_dataValue)).toInt();        // bool 类型值
                m_billValueDefaultList.append(Utils::reverseStr(it.m_dataValue));
            }
            else if (it.m_dataType == "10")
            {
                qDebug() << "数据类型为单点信息";
            }
            else if (it.m_dataType == "0C")
            {
                qDebug() << "数据类型为带品质描述的被测值";
            }
            else if (it.m_dataType == "13")
            {
                qDebug() << "数据类型为带时标的报文";
            }
            else if (it.m_dataType == "18")
            {
                qDebug() << "数据类型为数据结构";
            }
            else if (it.m_dataType == "CB")
            {
                qDebug() << "数据类型为带7字节的时标报文";
            }
            else if (it.m_dataType == "CC")
            {
                qDebug() << "数据类型为带相对时间的7字节时标报文";
            }
            else if(it.m_dataType == "00")
            {
                qDebug() << "数据类型为无所确定的类型";
            }
        }
        //最大值最小值步长
        else if (it.m_kod == "03")
        {
            qDebug() << "读取定值的最大最小值和步长"<< it.m_dataValue;
            if (it.m_dataNum =="03" || it.m_dataNum == "02")
            {
                if( it.m_dataType == "06" || it.m_dataType == "07") // 浮点数或者短实数
                {
                    qDebug() << "浮点数量程： "<<Utils::parseFloatTypeMinMaxStep(it.m_dataValue);
                    m_billValueMinList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[0]);
                    m_billValueMaxList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[1]);
                    m_billValueStepList.append(Utils::parseFloatTypeMinMaxStep(it.m_dataValue)[2]);
                }
                else if ( it.m_dataType == "03" )   // 整数量程
                {
                    qDebug() << "整数量程：" << it.m_dataValue << it.m_dataWidth << Utils::parseUIntType(it.m_dataValue, it.m_dataWidth.toUInt(nullptr,16));

                    switch ( Utils::parseIntTypeMinMaxStep(it.m_dataValue, it.m_dataWidth.toUInt(nullptr, 16)).count())
                    {
                        case 0 :
                        m_billValueMinList.append("no");
                        m_billValueMaxList.append("no");
                        m_billValueStepList.append("no");
                        break;
                    case 1 :
                        m_billValueMinList.append("no");
                        m_billValueMaxList.append("no");
                        m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[0]);
                        break;
                    case 2 :
                        m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[0]);
                        m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[1]);
                        m_billValueStepList.append("no");
                        break;
                    case 3:
                        m_billValueMinList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[0]);
                        m_billValueMaxList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[1]);
                        m_billValueStepList.append(Utils::parseUIntType(it.m_dataValue,it.m_dataWidth.toUInt(nullptr,16))[2]);
                        break;
                    }
                }
                else if (it.m_dataType == "01")  // ASCII8位码
                {
                    if(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue).count() !=3)
                    {
                        m_billValueMinList.append(" ");
                        m_billValueMaxList.append(" ");
                        m_billValueStepList.append(" ");
                    }
                    int width = it.m_dataWidth.toInt(nullptr,16);
                    QString  strList = Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue);
                    // 将strList按照 单个宽度进行分割
                    qDebug() << "ASCII8位码量程：" <<Utils::mixCharToWord(strList,width);
                    this->m_billValueMinList.append(Utils::mixCharToWord(strList,width)[0]);
                    m_billValueMaxList.append(Utils::mixCharToWord(strList,width)[1]);
                    m_billValueStepList.append(Utils::mixCharToWord(strList,width)[2]);
                }
            }
        }
        // 读取单位
        else if (it.m_kod == "09")
        {
          // qDebug() << "单位" <<  Utils::mixCharToWord(Utils::parseASCII8BTypeMinMaxStepUnit(it.m_dataValue),it.m_dataWidth.toInt(nullptr,16));
           qDebug() << "单位 GBKTOUTF8 :" << Utils::GBKToUTF8(it.m_dataValue);
           m_billValueUinitList.append( Utils::GBKToUTF8(it.m_dataValue) );
        }
    }
}

QString NZParser::findGroupNoByGroupName(const QString &groupName, vector<OneDataSetStruct> &dataSets)
{
    foreach (OneDataSetStruct it, dataSets)
    {
        if (it.m_kod == "0A" && Utils::GBKToUTF8(it.m_dataValue) == groupName )
        {
            return it.m_ginGroup;
        }
    }
    qDebug() << "not find the group.";

    return nullptr;
}




